#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"

#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/i2c.h"
#include "utils/uartstdio.h"
#include "driverlib/rom_map.h"
#include "utils/uartstdio.h"

#define I2CINUSE I2C1_MASTER_BASE

void i2c_init(void)
{
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);

	GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
	ROM_GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);

	ROM_GPIOPinConfigure(GPIO_PA6_I2C1SCL);
	ROM_GPIOPinConfigure(GPIO_PA7_I2C1SDA);

	ROM_I2CMasterInitExpClk(I2C1_MASTER_BASE, SysCtlClockGet(), false);
	ROM_I2CMasterTimeoutSet(I2C1_MASTER_BASE, 100);

	//ROM_I2CMasterIntEnable(I2C1_MASTER_BASE); we do not use
	//ROM_I2CMasterEnable(I2C1_MASTER_BASE); do not need

	while (ROM_I2CMasterBusy(I2C1_MASTER_BASE))
		;
}

void i2c_perform_scan(void)
{
	volatile int i;
	unsigned char cnt=0;

	UARTprintf("[BUSSCAN,");
	for (i = 0; i <= 255; ++i)
	{
		unsigned long ret = 0;
		// Specify slave address
		//
		ROM_I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, i, false);
		//
		// Place the character to be sent in the data register
		//
		ROM_I2CMasterDataPut(I2C1_MASTER_BASE, 0);
		//
		// Initiate send of character from Master to Slave
		//
		ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);
		//
		// Delay until transmission completes
		//
		while (ROM_I2CMasterBusy(I2C1_MASTER_BASE))
			;

		ret = ROM_I2CMasterErr(I2C1_MASTER_BASE);

		if (!ret)
		{
			cnt++;
			UARTprintf("%02x,", i);
			continue;
		}

		//    	if (ret & I2C_MASTER_ERR_ADDR_ACK)
		//		{
		//			UARTprintf("[I2C_MASTER_ERR_ADDR_ACK]");
		//		}
		//		 if (ret & I2C_MASTER_ERR_ARB_LOST)
		//		{
		//			UARTprintf("[I2C_MASTER_ERR_ARB_LOST]");
		//		}
		//		 if (ret & I2C_MASTER_ERR_CLK_TOUT)
		//		{
		//			UARTprintf("[I2C_MASTER_ERR_CLK_TOUT]");
		//		}
		//		 if (ret & I2C_MASTER_ERR_DATA_ACK)
		//		{
		//			UARTprintf("]I2C_MASTER_ERR_DATA_ACK]");
		//		}

	}
	UARTprintf("(%d)]\n",cnt);
}

unsigned char ReadRegister(unsigned char device, unsigned char address)
{
	I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, device, false);
	while (ROM_I2CMasterBusBusy(I2C1_MASTER_BASE));
	ROM_I2CMasterDataPut(I2C1_MASTER_BASE, address);
	ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);
	while (ROM_I2CMasterBusy(I2C1_MASTER_BASE));
	if(ROM_I2CMasterErr(I2C1_MASTER_BASE))
		UARTprintf("Some er1@ReadRegister\n");

	I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, device, true);
	ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
	while (ROM_I2CMasterBusy(I2C1_MASTER_BASE));
	if(ROM_I2CMasterErr(I2C1_MASTER_BASE))
		UARTprintf("Some er2@ReadRegister\n");
	return (unsigned char) I2CMasterDataGet(I2C1_MASTER_BASE);
}

short ReadRegisterW(unsigned char device, unsigned char address)
{
	short ret;

	I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, device, false);

	while ( (ROM_I2CMasterBusBusy(I2C1_MASTER_BASE)));

//	if (timeout==0)
//	{
//		UARTprintf("Read Timeout\n");
//		ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C1);
//		ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
//		return 0;
//	}

	ROM_I2CMasterDataPut(I2C1_MASTER_BASE, address);
	ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND);
	while (ROM_I2CMasterBusy(I2C1_MASTER_BASE));
	if(ROM_I2CMasterErr(I2C1_MASTER_BASE))
		UARTprintf("Some er1@ReadRegister\n");

	I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, device, true);
	ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
	while (ROM_I2CMasterBusy(I2C1_MASTER_BASE));
	if(ROM_I2CMasterErr(I2C1_MASTER_BASE))
		UARTprintf("Some er2@ReadRegister\n");

	ret = I2CMasterDataGet(I2C1_MASTER_BASE);
	ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
	while (ROM_I2CMasterBusy(I2C1_MASTER_BASE));
	if(ROM_I2CMasterErr(I2C1_MASTER_BASE))
		UARTprintf("Some er3@ReadRegister\n");

	return (ret | ((unsigned char)(I2CMasterDataGet(I2C1_MASTER_BASE))<<8));
}

void WriteRegister(unsigned char device, unsigned char address, unsigned char value)
{
	I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, device, false);
	ROM_I2CMasterDataPut(I2C1_MASTER_BASE, address);
	ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START);
	while (ROM_I2CMasterBusy(I2C1_MASTER_BASE));
	if(ROM_I2CMasterErr(I2C1_MASTER_BASE))
		UARTprintf("Some er1@WriteRegister\n");

	//while (ROM_I2CMasterBusBusy(I2C1_MASTER_BASE));
	//I2CMasterSlaveAddrSet(I2C1_MASTER_BASE, device, false);
	ROM_I2CMasterDataPut(I2C1_MASTER_BASE, value);
	ROM_I2CMasterControl(I2C1_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);

	while (ROM_I2CMasterBusy(I2C1_MASTER_BASE));
	if(ROM_I2CMasterErr(I2C1_MASTER_BASE))
		UARTprintf("Some er2@WriteRegister\n");

}
